using System.Reflection;
using System.Resources;

namespace BoxBinary.Foundations.OperationalManagement.Resources
{
    /// <summary>
    /// 
    /// </summary>
    public class LocalizedResourceReader
    {
        private static LocalizedResourceReader _default;

        protected internal LocalizedResourceReader()
        {
        }

        /// <summary>
        /// Gets the default.
        /// </summary>
        /// <value>The default.</value>
        public static LocalizedResourceReader Default
        {
            get
            {
                if (_default == null)
                    _default = new LocalizedResourceReader();
                return _default;
            }
        }

        /// <summary>
        /// Gets the default root namespace.
        /// </summary>
        /// <value>The default root namespace.</value>
        public string DefaultRootNamespace
        {
            get { return "CondeNetUK.FoundationServices"; }
        }

        protected string GetString(string overrideDefaultNamespace, string resourceNamespaceStub, string key,
                                   Assembly callingAssembly)
        {
            string returnString = string.Empty;
            try
            {
                returnString = GetStringFromSpecificAssembly(overrideDefaultNamespace, resourceNamespaceStub, key,
                                                             callingAssembly);
            }
            catch (MissingManifestResourceException)
            {
                // The resource file doesn't exist for the calling assembly
                // In this case we try and load from our own (executing) assembly
                // So we do nothing and bubble the empty returnString to the if statement outside of the
                // catch block... Ugly, but meh - it works
            }

            if (string.IsNullOrEmpty(returnString))
            {
                returnString = GetStringFromSpecificAssembly(DefaultRootNamespace, resourceNamespaceStub, key,
                                                             Assembly.GetExecutingAssembly());
            }

            return returnString;
        }

        /// <summary>
        /// Tries the get string.
        /// </summary>
        /// <param name="overrideDefaultNamespace">The override default namespace.</param>
        /// <param name="resourceNamespaceStub">The resource namespace stub.</param>
        /// <param name="key">The key.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <returns></returns>
        public string TryGetString(string overrideDefaultNamespace, string resourceNamespaceStub, string key,
                                   string defaultValue)
        {
            return TryGetString(overrideDefaultNamespace, resourceNamespaceStub, key, defaultValue,
                                Assembly.GetCallingAssembly());
        }

        /// <summary>
        /// Tries the get string.
        /// </summary>
        /// <param name="overrideDefaultNamespace">The override default namespace.</param>
        /// <param name="resourceNamespaceStub">The resource namespace stub.</param>
        /// <param name="key">The key.</param>
        /// <param name="defaultValue">The default value.</param>
        /// <param name="fromSpecificAssembly">From specific assembly.</param>
        /// <returns></returns>
        public string TryGetString(string overrideDefaultNamespace, string resourceNamespaceStub, string key,
                                   string defaultValue, Assembly fromSpecificAssembly)
        {
            try
            {
                return GetString(overrideDefaultNamespace, resourceNamespaceStub, key, fromSpecificAssembly);
            }
            catch
            {
                try
                {
                    return
                        GetString(overrideDefaultNamespace, resourceNamespaceStub, key, Assembly.GetCallingAssembly());
                }
                catch
                {
                    return defaultValue;
                }
            }
        }

        /// <summary>
        /// Gets the string from specific assembly.
        /// </summary>
        /// <param name="overrideDefaultNamespace">The override default namespace.</param>
        /// <param name="resourceNamespaceStub">The resource namespace stub.</param>
        /// <param name="key">The key.</param>
        /// <param name="assembly">The assembly.</param>
        /// <returns></returns>
        public string GetStringFromSpecificAssembly(string overrideDefaultNamespace, string resourceNamespaceStub,
                                                    string key, Assembly assembly)
        {
            return GetResourceManager(overrideDefaultNamespace, resourceNamespaceStub, assembly).GetString(key);
        }

        /// <summary>
        /// Gets the resource manager.
        /// </summary>
        /// <param name="overrideDefaultNamespace">The override default namespace.</param>
        /// <param name="resourceNamespaceStub">The resource namespace stub.</param>
        /// <param name="callingAssembly">The calling assembly.</param>
        /// <returns></returns>
        protected static ResourceManager GetResourceManager(string overrideDefaultNamespace,
                                                            string resourceNamespaceStub,
                                                            Assembly callingAssembly)
        {
            return
                new ResourceManager(
                    NonLocalizedResourceReader.GetResourceNamespace(overrideDefaultNamespace, resourceNamespaceStub),
                    callingAssembly);
        }
    }
}